package com.tianji.learning.service.impl;

import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.constants.MqConstants;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.constants.RedisConstants;
import com.tianji.learning.domain.dto.SignInMessage;
import com.tianji.learning.domain.vo.SignResultVO;
import com.tianji.learning.service.ISignRecordsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * TODO
 *
 * @Author wangxinyi
 * @Date 2025/1/11 16:01
 */
@Service
public class ISignRecordsServiceImpl implements ISignRecordsService {


    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RabbitMqHelper mqHelper;

    /**
     * 签到
     *
     * @return
     */
    @Override
    public SignResultVO getSign() {
        Long userId = UserContext.getUser();
        //获取当前年月
        LocalDateTime now = LocalDateTime.now();
        String yearMonth = DateUtils.format(now, "yyyyMM");
        String key = RedisConstants.SIGN_RECORD_KEY_PREFIX + userId + ":" + yearMonth;
        //获取当前日
        int dayOfMonth = now.getDayOfMonth();
        //将今日签到数据存入redis的bitmap中
        Boolean result = redisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);
        if (Boolean.TRUE.equals(result)) {
            //已经签到过了
            throw new BizIllegalException("不允许重复签到！");
        }
        //求出已经连续签到多少天
        Integer count = countSign(key, dayOfMonth);

        int rewardPoints = (count == 28) ? 40 :
                (count == 14) ? 20 :
                        (count == 7) ? 10 : 0;
        //封装结果
        SignResultVO signResultVO = new SignResultVO();
        signResultVO.setSignDays(count);
        signResultVO.setRewardPoints(rewardPoints);
        //添加积分记录
        key = MqConstants.Key.SIGN_IN;
        String exchange = MqConstants.Exchange.LEARNING_EXCHANGE;
        mqHelper.send(exchange, key,
                SignInMessage.of(userId, rewardPoints + 1));
        return signResultVO;
    }

    private Integer countSign(String key, Integer len) {
        //获取从今天到1号所有的签到记录
        List<Long> longList = redisTemplate.opsForValue()
                .bitField(key, BitFieldSubCommands.create()
                        .get(BitFieldSubCommands.BitFieldType.unsigned(len))
                        .valueAt(0));
        //其中 List<Long> longList 第一个存放的元素就是bitmap的十进制形式，结果用list返回是为了通用
        Long decimalStr = longList.get(0);
        String binaryString = Long.toBinaryString(decimalStr);//十进制转为二进制
        //遍历二进制求连续签到次数
        int count = 0;
        for (int i = binaryString.length() - 1; i >= 0; i--) {
            if (binaryString.charAt(i) == '1') {
                count++;
            } else {
                break;
            }
        }
        return count;
    }
}
